﻿////////////////////////
/// 进行场的计算和显示的类,FieldCalculation类提供对未计算过的场进行初始化计算.
/// FieldDisplay提供对已计算好的结果进行显示
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Data.SqlClient;
using System.Diagnostics;

using ESRI.ArcGIS.SystemUI;
using ESRI.ArcGIS.Geometry;
using ESRI.ArcGIS.Carto;
using ESRI.ArcGIS.Display;
using ESRI.ArcGIS.Controls;
using ESRI.ArcGIS.Geodatabase;
using ESRI.ArcGIS.Geoprocessing;
using ESRI.ArcGIS.Geoprocessor;
using ESRI.ArcGIS.DataSourcesFile;
using ESRI.ArcGIS.AnalysisTools;
using esri.ParaSeting;
using esri.DataBase;
using esri.Detect;
using esri3;
using esri;

namespace esri_field
{
    //
    //直接读取计算好的结果
    //
    namespace Field_Read
    {
    }
    //
    //对未进行计算的场进行计算
    //
    namespace Field_Calculation
    {
        class FieldCalculation
        {
            public FieldCalculation()
            { }

            /// <summary>
            /// 场计算类,包括初始化点数组(删除相同的点),初始化所选择场的格子数组,以及给格子赋以相应的高程
            /// </summary>
            /// 
            public bool UpdataDB = false;
            public void Elevation_Calculation(string fieldno,double P_Range,double PG_Range,MainForm frm)
            {
                
                
                Point_Initial(fieldno,P_Range);
                
                
                
                Grid_Initial(frm,PG_Range);
                
                
                Elevation_Decide();
                
            }
            struct pt
            {
                
                public double x;
                public double y;
                public double h;
                public bool ischecked;
            }


            pt temppoint = new pt();
            ArrayList tempPointArray = new ArrayList();
            pt[] PointArray;
            ///
            ///点数组的初始化,去除距离在0.1内的点
            ///

            void Point_Initial(string field,double range)
            {
                DBConnection DBC = DBConnection.Instance();
                DBOperation DBO_name = new DBOperation();
                DBO_name.ConnectionString = DBC.ConnectionString;
                SqlConnection conn_name = DBO_name.Connect();
                //根据场号先查得表名
                int number_point=0;
                string str_name,str_query,str_query_count;
                str_name = "SELECT name FROM sys.sysobjects WHERE (xtype = 'U') AND (name LIKE '%TBLGPSDATA_1000_133_" + field.ToString() + "%')";
                SqlCommand cmd_name = new SqlCommand(str_name, conn_name);
                SqlDataReader dr_name = cmd_name.ExecuteReader();
                ProgressBar pBar=new ProgressBar();
                string str_text="";
                pBar.Text = str_text;
                pBar.progressBar1.Minimum = 0;
                pBar.Show();
                int table_number = 0;

                int tableCutPos = 0;
                while(dr_name.Read())
                {
                    tableCutPos = tempPointArray.Count;
                    
                    table_number++;
                    str_text = "初始化GPS数据表" + table_number.ToString();
                    str_query="SELECT * FROM  dbo." + dr_name[0].ToString() + " WHERE (STATUE = 4)";
                    str_query_count="SELECT count(*) FROM  dbo." + dr_name[0].ToString() + " WHERE (STATUE = 4)";
                    DBOperation DBO_query =new DBOperation();
                    DBO_query.ConnectionString=DBC.ConnectionString;
                    SqlConnection conn_query=DBO_query.Connect();
                    SqlCommand cmd_query=new SqlCommand(str_query_count,conn_query);
                    number_point=Convert.ToInt32(cmd_query.ExecuteScalar());

                    
                    int pvalue=0;
                    pBar.progressBar1.Value = pvalue;
                    pBar.progressBar1.Maximum=number_point;

                    cmd_query.CommandText=str_query;
                    SqlDataReader dr_query=cmd_query.ExecuteReader();
                    
                    while(dr_query.Read())
                    {
                        bool flag=true;
                        temppoint.x = Convert.ToDouble(dr_query.GetValue(8));
                        temppoint.y = Convert.ToDouble(dr_query.GetValue(7));
                        temppoint.h = Convert.ToDouble(dr_query.GetValue(9));
                        temppoint.ischecked = false;
                        if (tempPointArray.Count == 0)
                            tempPointArray.Add(temppoint);
                        else
                        {
                            pt temp = new pt();

                            for (int i = tableCutPos; i < tempPointArray.Count; i++)
                            {
                                
                                temp = (pt)tempPointArray[i];
                                double temp_dis =
                                    Math.Sqrt((temp.x - temppoint.x)*(temp.x - temppoint.x) +
                                              (temp.y - temppoint.y)*(temp.y - temppoint.y));
                                if ((temp_dis!=0)&&(temp_dis<range))
                                {
                                    flag = false;
                                    break;
                                }
                            }
                            if (flag)
                            {
                                tempPointArray.Add(temppoint);
                                
                            }
                        }
                        pvalue++;
                        pBar.progressBar1.Value = pvalue;
                        int scale=(int)(Convert.ToDouble(pvalue)/Convert.ToDouble(pBar.progressBar1.Maximum)*100.0);
                        
                        pBar.Text = str_text + " " + scale.ToString() + "%";
                        
                    }
                    dr_query.Close();
                    conn_query.Close();
                }

                dr_name.Close();
                PointArray = new pt[tempPointArray.Count];
                tempPointArray.CopyTo(PointArray);
                tempPointArray.Clear();
                conn_name.Close();
                pBar.Hide();
            }
            ///
            ///格子数组坐标的初始化,根据裁剪好的格子,遍历之,根据其FID在SQL表中得到坐标，并通过判断之前初始化后的点与格子做坐标的比较，距离0.25-0.001的即认为点在格子内，将
            /// 点的坐标赋给格子
            ///
            internal struct grid
            {
                public string GID;
                public double x;
                public double y;
                public double fh;
                public double lh;
                
                public int p_count;
            }

            double[,] H;
            grid tempgrid = new grid();
            ArrayList tempGridArray = new ArrayList();
            grid[] GridArray;
            int Gridcount;
            public bool findlayer=false;

            void Grid_Initial(MainForm m_this,double range)
            {
                
                DBConnection DBC = DBConnection.Instance();
                DBOperation DBO_name = new DBOperation();
                DBO_name.ConnectionString = DBC.ConnectionString;
                SqlConnection conn = DBO_name.Connect();
                SqlCommand cmd=new SqlCommand();
                cmd.Connection = conn;
                SqlDataReader dr;

                ProgressBar pBar = new ProgressBar();
                
                //得到MapControl中的MainGrid图层
                AxMapControl m_map = m_this.MapControl;
                int i, j, k,layer_index=0,FID_index=0,X_index=0,Y_index=0;
                bool find = false;
                ILayer pLayer;
                
                for (i = 0; i < m_map.LayerCount; i++)
                {
                    pLayer = m_map.get_Layer(i);
                    
                    if (pLayer.Name == "MainGrid")
                    {
                        findlayer = true;
                        layer_index = i;
                        find = true;
                        break;
                    }                    
                }
                if (find)
                    pLayer = m_map.get_Layer(layer_index);
                else
                {
                    return;
                }
                ////////////
                /// 遍历裁剪后的图层，使用SELECT在格子结果表中查找其坐标，用来初始化格子数组
                IFeatureLayer pFeatureLayer = (IFeatureLayer) pLayer;
                
                IFeatureClass pFeatureClass = pFeatureLayer.FeatureClass;
                
                ICursor pCursor = (ICursor)pFeatureClass.Search(null,true);
                
                IRow pRow;
                IFields pFields=pCursor.Fields;
                IField pField;
                object FieldValue;
                for(k=0;k<pFields.FieldCount;k++)
                {
                    
                    pField = pFields.get_Field(k);
                    if(pField.Name=="Id")
                    {
                        FID_index = k;
                        
                        
                    }
                    if (pField.Name == "Center_X")
                        X_index = k;
                    if(pField.Name=="Center_Y")
                        Y_index = k;
                }
                Gridcount = pFeatureClass.FeatureCount(null);
                pBar.progressBar1.Maximum = Gridcount;
                pBar.progressBar1.Value = 0;
                int count = 0,scale=0;
                string str_name = "正在初始化格子数组";
                pBar.Text = str_name;
                pBar.Show();
                pRow = pCursor.NextRow();

                H=new double[Gridcount,100];
                int index1 = 0, index2 = 0;
                double dis;
                
                while(pRow!=null)
                {
                    
                    
                    FieldValue = pRow.get_Value(FID_index);
                    
                    tempgrid.GID = FieldValue.ToString();
                    tempgrid.x = Convert.ToDouble(pRow.get_Value(X_index));
                    tempgrid.y = Convert.ToDouble(pRow.get_Value(Y_index));
                    for (j = 0; j < PointArray.Length;j++ )
                    {
                        if (!PointArray[j].ischecked)
                        {
                            dis =
                                Math.Sqrt((PointArray[j].x - tempgrid.x) * (PointArray[j].x - tempgrid.x) +
                                          (PointArray[j].y - tempgrid.y)*(PointArray[j].y - tempgrid.y));
                            if (dis <= range)
                            {
                                if (!inh(H, PointArray[j].h,index1))
                                {
                                    H[index1, index2] = PointArray[j].h;
                                    index2++;
                                }
                                PointArray[j].ischecked = true;
                            }
                        }
                    }
                    index1++;
                    tempgrid.p_count = index2;
                    tempGridArray.Add(tempgrid);
                    index2 = 0;
                    pRow = pCursor.NextRow();
                    
                    count++;
                    pBar.progressBar1.Value = count;
                    scale = (int)(Convert.ToDouble(count) / Convert.ToDouble(pBar.progressBar1.Maximum) * 100.0);
                    pBar.Text = str_name + "   " + scale.ToString() + "%";
                }

                GridArray = new grid[tempGridArray.Count];
                tempGridArray.CopyTo(GridArray);
                tempGridArray.Clear();
                pBar.Hide();
                
            }
            bool inh(double[,]arr,double temph,int row)
            {
                bool result=false;
                for(int i=0;i<10;i++)
                {
                    if(arr[row,i]==temph)
                    {
                        result = true;
                        break;
                    }
                }
                return result;
            }

            void Elevation_Decide()
            {
                ProgressBar pBar = new ProgressBar();
                string str_name = "第一遍初始化高程" + "   ";
                pBar.Text = str_name;
                pBar.progressBar1.Maximum = Gridcount;
                pBar.progressBar1.Value = 0;
                pBar.Show();
                int i, j, k;
                double maxh, minh, temph;
                if(Gridcount<=0)
                    return;
                for(i=0;i<Gridcount;i++)
                {
                    /////////
                    /// 如果格子内的点数>=2时,直接将最大值赋给firstH最小值赋给lastH
                    if (GridArray[i].p_count >= 2)
                    {
                        
                        maxh = H[i, 0];
                        minh = H[i, 0];
                        
                        for (j = 1; j < GridArray[i].p_count; j++)
                        {
                            
                            if (maxh < H[i, j])
                                maxh = H[i, j];


                            if (minh > H[i, j])
                                minh = H[i, j];
                        }
                        GridArray[i].fh = maxh;
                        GridArray[i].lh = minh;

                    }
                    pBar.progressBar1.Value = i;
                    int scale = (int)(Convert.ToDouble(i) / Convert.ToDouble(pBar.progressBar1.Maximum) * 100.0);

                    pBar.Text = str_name + scale.ToString() + "%";
                }
                pBar.progressBar1.Value = 0;
                str_name = "第二遍初始化高程" + "   ";
                for(i=0;i<Gridcount;i++)
                {
                    //////////
                    /// 如果格子内的点只有一个,高程赋给临时值,插值得到两个高程,并做比较,三者最大为FH,最小为LH
                    if (GridArray[i].p_count == 1)
                    {
                        temph = H[i, 0];
                        maxh = Interpolation_FH(GridArray[i], 9);
                        minh = Interpolation_LH(GridArray[i], 9);
                        if (maxh < temph)
                            maxh = temph;
                        else if (minh > temph)
                            minh = temph;
                        GridArray[i].fh = maxh;
                        GridArray[i].lh = minh;
                    }
                    pBar.progressBar1.Value = i;
                    int scale = (int)(Convert.ToDouble(i) / Convert.ToDouble(pBar.progressBar1.Maximum) * 100.0);

                    pBar.Text = str_name + scale.ToString() + "%";
                }
                pBar.progressBar1.Value = 0;
                str_name = "第三遍初始化高程" + "   ";
                for(i=0;i<Gridcount;i++)
                {
                    ////////
                    /// 如果格子内没有点,则插 值得到两个高程
                    if (GridArray[i].p_count == 0)
                    {
                        GridArray[i].fh = Interpolation_FH(GridArray[i], 9);
                        GridArray[i].lh = Interpolation_LH(GridArray[i], 9);
                    }
                    pBar.progressBar1.Value = i;
                    int scale = (int)(Convert.ToDouble(i) / Convert.ToDouble(pBar.progressBar1.Maximum) * 100.0);

                    pBar.Text = str_name + scale.ToString() + "%";

                }
            
                    
                
                pBar.Hide();
            }
            double Interpolation_FH(grid m_grid, double range)
            {
                double disSum = 0; //符合条件的格子的距离总合
                ArrayList dis = new ArrayList(); //符合条件的格子的各自的距离
                double temp_dis;
                ArrayList weight = new ArrayList(); //权重数组
                ArrayList temp_weight = new ArrayList();
                int pos = 0; //两个数组的下标
                int grid_count; //符合条件的邻近格子数
                ArrayList gridNumber = new ArrayList();
                for (int i = 0; i < Gridcount; i++)
                {
                    if (GridArray[i].fh > 0)
                    {
                        temp_dis =
                            Math.Sqrt(Math.Pow(m_grid.x - GridArray[i].x, 2) + Math.Pow(m_grid.y - GridArray[i].y, 2));
                        //grid与GridArray[i]的距离;
                        if (temp_dis < range)
                        {
                            dis.Add(temp_dis);
                            gridNumber.Add(i);
                            pos++;
                        }
                    }
                }
                double result_FH = 0;
                if (pos > 0)
                {
                    //下面按反距离确定权重
                    int j, k;
                    for (j = 0; j < pos; j++)
                        disSum  += (double) dis[j];
                    for (k = 0; k < pos; k++)
                        temp_weight.Add(disSum/(double) dis[k]);
                    double temp_sum = 0.0;
                    for (j = 0; j < pos; j++)
                        temp_sum += (double) temp_weight[j];
                    for (j = 0; j < pos; j++)
                        weight.Add((double) temp_weight[j]/temp_sum);
                    //计算结果

                    for (j = 0; j < pos; j++)
                        result_FH += (double) weight[j]*GridArray[(int) gridNumber[j]].fh;
                }
                return Math.Round(result_FH,3);
            }



            double Interpolation_LH(grid m_grid, double range)
            {
                double disSum = 0;//符合条件的格子的距离总合
                ArrayList dis = new ArrayList();//符合条件的格子的各自的距离
                double temp_dis;
                ArrayList weight = new ArrayList();//权重数组
                ArrayList temp_weight = new ArrayList();
                int pos = 0;//两个数组的下标
                int grid_count;//符合条件的邻近格子数
                ArrayList gridNumber = new ArrayList();
                for (int i = 0; i < Gridcount; i++)
                {
                    if (GridArray[i].lh > 0)
                    {
                        temp_dis =
                            Math.Sqrt(Math.Pow(m_grid.x - GridArray[i].x, 2) + Math.Pow(m_grid.y - GridArray[i].y, 2));
                            //grid与GridArray[i]的距离;
                        if (temp_dis < range)
                        {
                            dis.Add(temp_dis);
                            gridNumber.Add(i);
                            pos++;
                        }
                    }
                }
                double result_LH = 0;
                //下面按反距离确定权重
                if (pos > 0)
                {
                    int j, k;
                    for (j = 0; j < pos; j++)
                        disSum += (double) dis[j];
                    for (k = 0; k < pos; k++)
                        temp_weight.Add(disSum/(double) dis[k]);
                    double temp_sum = 0.0;
                    for (j = 0; j < pos; j++)
                        temp_sum += (double) temp_weight[j];
                    for (j = 0; j < pos; j++)
                        weight.Add((double) temp_weight[j]/temp_sum);
                    //计算结果
                    
                    for (j = 0; j < pos; j++)
                        result_LH += (double) weight[j]*GridArray[(int) gridNumber[j]].lh;
                }
                return Math.Round(result_LH,3);
            }
            public void Elevation_UpdateDB(string tablename)
            {
                DBConnection DBC = DBConnection.Instance();
                DBOperation DBO = new DBOperation();
                DBO.ConnectionString = DBC.ConnectionString;
                SqlConnection conn = DBO.Connect();
                string str_create, str_open;
                str_create = "create table dbo.GPSTBL_H_" + tablename.Insert(4, "_") + " " + "(GID char(20),Center_X real,Center_Y real,First_H real,Last_H real)";
                SqlCommand cmd_create = new SqlCommand(str_create, conn);
                cmd_create.ExecuteNonQuery();
                cmd_create.Dispose();

                str_open = "select * from dbo.GPSTBL_H_" + tablename.Insert(4, "_");
                SqlDataAdapter da = new SqlDataAdapter(str_open, conn);
                SqlCommandBuilder cmdBuilder = new SqlCommandBuilder(da);
                da.InsertCommand = cmdBuilder.GetInsertCommand();

                DataSet ds = new DataSet();
                da.FillSchema(ds, SchemaType.Mapped);
                DataTable dt = ds.Tables[0];


                /////////////////////////////////////////////////////////////
                ProgressBar pBar=new ProgressBar();
                pBar.Text = "计算结果入库";
                pBar.progressBar1.Maximum = Gridcount;
                pBar.progressBar1.Value = 0;
                pBar.Show();
                for (int i = 0; i < Gridcount; i++)
                {
                    DataRow row = dt.NewRow();
                    row["GID"] = GridArray[i].GID;
                    row["Center_X"] = GridArray[i].x;
                    row["Center_Y"] = GridArray[i].y;
                    row["First_H"] = GridArray[i].fh;
                    row["Last_H"] = GridArray[i].lh;
                    dt.Rows.Add(row);
                    pBar.progressBar1.Value = i;
                }
                da.Update(ds);
                UpdataDB = true;
                conn.Close();
                pBar.Hide();
                
            }

        }
        class testparm
        {
            public string testfrm(IFeatureClass m_FeatureClass)
            {
                
                string str;
                str = m_FeatureClass.AliasName;
                return str;
            }
            public string testfrm1(AxMapControl m_map)
            {
                string str;
                str = m_map.get_Layer(0).Name;
                return str;
            }
            public string testfrm2(MainForm frm)
            {
                string str;
                str = frm.MapControl.get_Layer(0).Name;
                return str;
            }
        }

        ////////////////////
        /// 场的结果显示
        /// 场数据的初始化
        ////////////////////////
        class FieldInitial
        {
            public int GridCount;//记录&格子的总数
            public IPoint pt = new PointClass();
            public double Xextent=0, Yextent=0;
            public int x25 = 0, y25 = 0;
            public double sumh=0, averageh = 0;
            private static FieldInitial finit;//静态的存储结果变量
            public static FieldInitial CtInstance()
            {
                if (finit == null)
                    finit = new FieldInitial();
                return finit;
            }
            public FieldInitial()
            {}
            public struct ResGrid
            {
                public string Id;//格子ID
                public double X;//X坐标
                public double Y;//Y坐标
                public double Fh;//firsth
                public double Lh;//lasth

            }

            public ResGrid[] mCurrentGrid, mFormerGrid;

            public void CurrentInitial(string fieldno)
            {
                DBConnection DBC = DBConnection.Instance();
                DBOperation DBO = new DBOperation();
                DBO.ConnectionString = DBC.ConnectionString;
                SqlConnection conn = DBO.Connect();
                string cmdstr = "select * from GPSTBL_H_" + fieldno.Insert(4, "_");
                string cmdquery = "select count(*) from GPSTBL_H_" + fieldno.Insert(4, "_");
                SqlCommand cmd = new SqlCommand();
                cmd.Connection = conn;
                cmd.CommandText = cmdquery;
                GridCount = (int) cmd.ExecuteScalar();
                mCurrentGrid = new ResGrid[GridCount];
                ProgressBar pBar=new ProgressBar();
                pBar.Text = "初始化结果";
                pBar.progressBar1.Value = 0;
                pBar.progressBar1.Maximum = GridCount;
                pBar.Show();
                int index = 0;
                cmd.CommandText = cmdstr;
                SqlDataReader dr = cmd.ExecuteReader();
                while(dr.Read())
                {
                    mCurrentGrid[index].Id = dr.GetValue(0).ToString();
                    mCurrentGrid[index].X = Convert.ToDouble(dr.GetValue(1));
                    mCurrentGrid[index].Y = Convert.ToDouble(dr.GetValue(2));
                    mCurrentGrid[index].Fh = Convert.ToDouble(dr.GetValue(3));
                    mCurrentGrid[index].Lh = Convert.ToDouble(dr.GetValue(4));
                    sumh += mCurrentGrid[index].Lh;
                    index++;
                    pBar.progressBar1.Value = index;
                }
                averageh = sumh/GridCount;
                pBar.Hide();
                DBO.CloseConnection();
            }

            public void FormerInitial(string fieldno)
            {
                DBConnection DBC = DBConnection.Instance();
                DBOperation DBO = new DBOperation();
                DBO.ConnectionString = DBC.ConnectionString;
                SqlConnection conn = DBO.Connect();
                string cmdstr = "select * from GPSTBL_H_" + fieldno.Insert(4, "_");
                string cmdquery = "select count(*) from GPSTBL_H_" + fieldno.Insert(4, "_");
                SqlCommand cmd = new SqlCommand();
                cmd.Connection = conn;
                cmd.CommandText = cmdquery;
                GridCount = (int)cmd.ExecuteScalar();

                mFormerGrid = new ResGrid[GridCount];
                ProgressBar pBar = new ProgressBar();
                pBar.Text = "初始化结果";
                pBar.progressBar1.Value = 0;
                pBar.progressBar1.Maximum = GridCount;
                pBar.Show();
                int index = 0;
                cmd.CommandText = cmdstr;
                SqlDataReader dr = cmd.ExecuteReader();
                while (dr.Read())
                {
                    mFormerGrid[index].Id = dr.GetValue(0).ToString();
                    mFormerGrid[index].X = Convert.ToDouble(dr.GetValue(1));
                    mFormerGrid[index].Y = Convert.ToDouble(dr.GetValue(2));
                    mFormerGrid[index].Fh = Convert.ToDouble(dr.GetValue(3));
                    mFormerGrid[index].Lh = Convert.ToDouble(dr.GetValue(4));
                    index++;
                    pBar.progressBar1.Value = index;
                }
                pBar.Hide();
                DBO.CloseConnection();
            }

        }
                
                
    }
}